#ifdef _MSC_VER
# pragma warning(disable:4251)
# pragma warning(disable:4458)
# pragma warning(disable:4819) // Unicode / Utf-16LE
#endif //MSVC

#ifndef JXQGLOBAL_H
#define JXQGLOBAL_H

#include <cstdint>
#include <clocale>

#ifdef __GNUC__
# include <cxxabi.h>
#endif

#if defined(_WIN32) || defined(_WIN64) //window NT
# define J_OS_WIN
#elif defined(__unix) //unix
# define J_OS_UNIX
# ifdef __linux //linux
#  define J_OS_LINUX
# endif //linux
#endif //win/unix

#define J_DISABLE_COPY(Class) \
	Class(const Class &) = delete;\
	Class &operator=(const Class &) = delete;

#define J_DISABLE_MOVE(Class) \
	Class(Class &&) = delete; \
	Class &operator=(Class &&) = delete;

#define J_DISABLE_COPY_MOVE(Class) \
	J_DISABLE_COPY(Class) \
	J_DISABLE_MOVE(Class)

#define DO_WHILE(condition, content) \
	do { content } while(condition);

#define DO_WHILE_0(content) \
	DO_WHILE(0, content)

/*-----------------------------------------------------------------------*/

namespace JXQ
{

// 地址宽度
#if defined(_WIN64) || defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__)
# define J_OS_64BIT
typedef uint64_t  AddressBitsWide;
#else
# define J_OS_32BIT
typedef uint32_t  AddressBitsWide;
#endif // 32bit & 64bit

#ifdef J_OS_WIN
typedef AddressBitsWide JHandle;
#else
typedef signed int      JHandle;
#endif

// 地址转换器: 可以将任何类型的指针的地址转换成数值
template <typename T>
union AddrTlr
{
	T ptr;
	AddressBitsWide addr;
	explicit AddrTlr(T ptr) : ptr(ptr) {}
	explicit AddrTlr(AddressBitsWide addr) : addr(addr) {}
	AddrTlr() {}
};

} //namespace JXQ

/*-----------------------------------------------------------------------*/

// 类型转换
#define J_SCT(Type, Variable)  static_cast<Type>(Variable)
#define J_RCT(Type, Variable)  reinterpret_cast<Type>(Variable)
#define J_DCT(Type, Variable)  dynamic_cast<Type>(Variable)
#define J_CCT(Type, Variable)  const_cast<Type>(Variable)

/*-----------------------------------------------------------------------*/

#ifdef J_OS_WIN
# define J_DECL_EXPORT     __declspec(dllexport)
# define J_DECL_IMPORT     __declspec(dllimport)
# define J_DECL_HIDDEN
#else // win
# define J_DECL_EXPORT     __attribute__((visibility("default")))
# define J_DECL_IMPORT     __attribute__((visibility("default")))
# define J_DECL_HIDDEN     __attribute__((visibility("hidden")))
#endif // os

#ifdef __GNUC__
# define J_DECL_USED       __attribute__((used))
# define J_DECL_UNUSED     __attribute__((unused))
# define J_DECL_NORETURN   __attribute__((noreturn))
#else //msvc
# define J_DECL_USED
# define J_DECL_UNUSED
# define J_DECL_NORETURN
#endif

/*-----------------------------------------------------------------------*/

#ifdef __BUILD_JXQ_LIB
# define JXQLIB_EXPORT  J_DECL_EXPORT
#else
# define JXQLIB_EXPORT  J_DECL_IMPORT
#endif // export_import

#if defined(_MSC_VER)// && _MSC_VER < 1920
# define and  &&
# define or   ||
# define not   !
#endif

#define J_UNUSED(x) (void)(x)

/*-----------------------------------------------------------------------*/

#ifdef __GNUC__
# define ABI_CXA_DEMANGLE(name)  abi::__cxa_demangle(name, 0,0,0)
#else //Microsoft compilers need no special handling
# define ABI_CXA_DEMANGLE(name)  name
#endif

#ifdef UNICODE //user custom macro
# define jtr(str)   L##str
#else
# define jtr(str)   str
#endif

/*-----------------------------------------------------------------------*/

// 子类的私有属性
#define J_DECLARE_PRIVATE(Class) \
	private: \
	inline Class##Private *d_func() { return reinterpret_cast<Class##Private*>(d_ptr); } \
	inline const Class##Private *d_func() const { return reinterpret_cast<const Class##Private*>(d_ptr); } \
	friend class Class##Private;

// 子类的公有属性
#define J_DECLARE_PUBLIC(Class) \
	public: \
	inline Class *q_func() { return reinterpret_cast<Class*>(q_ptr); } \
	inline const Class *q_func() const { return reinterpret_cast<const Class*>(q_ptr); } \
	friend class Class;

// 得到d指针
#define J_D(Class) Class##Private * const d = d_func();
#define J_C_D(Class) const Class##Private * const d = d_func();

// 得到q指针
#define J_Q(Class) Class * const q = q_func();
#define J_C_Q(Class) const Class * const q = q_func();


#endif //JXQGLOBAL_H
